<!DOCTYPE html>
<html lang="zh">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>前端部署工具</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      font-family: 'Segoe UI', system-ui, sans-serif;
    }

    body {
      display: flex;
      flex-direction: column;
      height: 100vh;
      background: #f0f2f5;
      padding: 15px;
      overflow: hidden;
    }

    .container {
      max-width: 1400px;
      margin: 0 auto;
      width: 100%;
      display: flex;
      flex-direction: column;
      height: 100%;
    }

    header {
      display: flex;
      align-items: baseline;
      margin-bottom: 20px;
      padding-bottom: 15px;
      border-bottom: 1px solid #d0d7de;
    }

    .title {
      margin-right: 20px;
      font-size: 1.8rem;
      color: #24292f;
      font-weight: 500;
      margin-bottom: 5px;
    }

    .subtitle {
      font-size: 0.9rem;
      color: #57606a;
    }

    .deploy-form {
      display: flex;
      gap: 15px;
      margin-bottom: 20px;
      flex-wrap: wrap;
      background: white;
      border-radius: 8px;
      padding: 15px;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
    }

    .form-group {
      flex: 1;
      display: flex;
      align-items: center;
    }

    .form-label {
      display: block;
      font-size: 0.85rem;
      color: #57606a;
      margin-bottom: 5px;
      font-weight: 500;
    }

    select {
      width: 60%;
      padding: 3px 10px;
      margin-left: 20px;
      font-size: 0.95rem;
      border: 1px solid #d0d7de;
      border-radius: 6px;
      background-color: #ffffff;
      outline: none;
      transition: border 0.2s;
    }

    select:focus {
      border-color: #0969da;
      box-shadow: 0 0 0 3px rgba(9, 105, 218, 0.1);
    }

    .deploy-btn-container {
      display: flex;
      align-items: flex-end;
      flex-shrink: 0;
    }

    #deployBtn {
      padding: 3px 10px;
      font-size: 1rem;
      color: white;
      background-color: #0969da;
      border: none;
      border-radius: 6px;
      cursor: pointer;
      transition: background 0.2s;
      height: 35px;
    }

    #deployBtn:hover:enabled {
      background-color: #0a58ca;
    }

    #deployBtn:disabled {
      background-color: #8c959f;
      cursor: not-allowed;
    }

    .log-container {
      flex: 1;
      display: flex;
      flex-direction: column;
      background: #0d1117;
      border-radius: 8px;
      overflow: hidden;
      box-shadow: 0 3px 8px rgba(0, 0, 0, 0.1);
    }

    .log-header {
      background: #161b22;
      color: #e6edf3;
      padding: 12px 15px;
      font-size: 0.9rem;
      display: flex;
      justify-content: space-between;
      border-bottom: 1px solid #30363d;
    }

    .log-controls {
      display: flex;
      gap: 10px;
    }

    .log-btn {
      padding: 5px 10px;
      background: #30363d;
      border: 1px solid #30363d;
      color: #e6edf3;
      border-radius: 4px;
      cursor: pointer;
      font-size: 0.85rem;
    }

    .log-btn:hover {
      background: #343942;
    }

    #log {
      flex: 1;
      padding: 15px;
      font-size: 0.95rem;
      color: #e6edf3;
      overflow-y: auto;
      font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
      line-height: 1.6;
    }

    .log-line {
      margin-bottom: 7px;
      word-break: break-all;
    }

    .log-info {
      color: #7ee787;
    }

    .log-warning {
      color: #ffd33d;
    }

    .log-error {
      color: #ff7b72;
    }

    .status-indicator {
      display: flex;
      align-items: center;
      gap: 8px;
      font-size: 0.85rem;
      color: #8b949e;
    }

    .status-dot {
      width: 8px;
      height: 8px;
      border-radius: 50%;
      background: #3fb950;
    }

    @media (max-width: 800px) {
      .deploy-form {
        flex-direction: column;
      }

      .form-group {
        min-width: 100%;
      }

      .deploy-btn-container {
        width: 100%;
        justify-content: flex-end;
      }

      #deployBtn {
        width: 100%;
        padding: 10px;
      }
    }
  </style>
</head>

<body>
  <div class="container">
    <header>
      <div class="title">前端部署工具</div>
      <div class="subtitle">快速选择分支和环境进行一键部署</div>
    </header>

    <div class="deploy-form">
      <div class="form-group">
        <label class="form-label">选择分支</label>
        <select id="branchSelect">
          <option value="" disabled selected>加载分支中...</option>
        </select>
      </div>

      <div class="form-group">
        <label class="form-label">选择环境</label>
        <select id="envSelect">
          <option value="" disabled selected>请选择环境</option>
          <option value="test">测试环境</option>
          <option value="production">生产环境</option>
        </select>
      </div>

      <div class="deploy-btn-container">
        <button id="deployBtn">开始部署</button>
      </div>
    </div>

    <div class="log-container">
      <div class="log-header">
        <div class="status-indicator">
          <div class="status-dot" id="statusDot"></div>
          <span id="statusText">就绪</span>
        </div>
        <div class="log-controls">
          <button class="log-btn" id="clearLogBtn">清除日志</button>
          <button class="log-btn" id="copyLogBtn">复制日志</button>
        </div>
      </div>

      <div id="log">
        <div class="log-line log-info">[系统] 欢迎使用前端部署工具</div>
        <div class="log-line log-info">[系统] 请选择分支和部署环境</div>
      </div>
    </div>
  </div>

  <script>
    // 页面加载时获取分支列表
    document.addEventListener('DOMContentLoaded', async () => {
      await fetchBranches()
      updateStatus('ready', '就绪')
    })

    // 元素引用
    const branchSelect = document.getElementById('branchSelect')
    const envSelect = document.getElementById('envSelect')
    const deployBtn = document.getElementById('deployBtn')
    const logDiv = document.getElementById('log')
    const clearLogBtn = document.getElementById('clearLogBtn')
    const copyLogBtn = document.getElementById('copyLogBtn')
    const statusDot = document.getElementById('statusDot')
    const statusText = document.getElementById('statusText')

    // 状态颜色映射
    const statusColors = {
      ready: '#3fb950',      // 绿色
      progress: '#1f6feb',  // 蓝色
      error: '#f85149',      // 红色
      success: '#3fb950'    // 绿色
    }

    // 更新状态显示
    function updateStatus (state, text) {
      statusDot.style.background = statusColors[state]
      statusText.textContent = text
    }

    // 添加日志行
    function addLog (message, type = 'info') {
      const now = new Date()
      const timestamp = `[${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}]`

      const logLine = document.createElement('div')
      logLine.className = 'log-line'

      const messageSpan = document.createElement('span')
      messageSpan.className = `log-${type}`
      messageSpan.textContent = `${timestamp} ${message}`

      logLine.appendChild(messageSpan)
      logDiv.appendChild(logLine)

      // 自动滚动到底部
      logDiv.scrollTop = logDiv.scrollHeight
    }

    // 从服务器获取分支数据
    async function fetchBranches () {
      updateStatus('progress', '加载分支中...')

      try {
        const response = await fetch('http://localhost:3333/branches')

        if (!response.ok) {
          throw new Error(`获取分支失败: ${response.status}`)
        }

        const branches = await response.json()

        // 清空并添加选项
        branchSelect.innerHTML = ''
        const defaultOption = document.createElement('option')
        defaultOption.value = ''
        defaultOption.textContent = '请选择分支'
        defaultOption.disabled = true
        defaultOption.selected = true
        branchSelect.appendChild(defaultOption)

        // 添加分支选项
        branches.forEach(branch => {
          const option = document.createElement('option')
          option.value = branch
          option.textContent = branch
          branchSelect.appendChild(option)
        })

        updateStatus('ready', '就绪')
        addLog('[系统] 成功加载分支列表', 'info')
      } catch (error) {
        console.error('获取分支失败:', error)
        addLog(`[错误] 无法获取分支列表: ${error.message}`, 'error')
        updateStatus('error', '加载失败')

        // 添加重试选项
        const retryOption = document.createElement('option')
        retryOption.textContent = '加载失败，点击重试'
        branchSelect.appendChild(retryOption)

        branchSelect.addEventListener('change', () => {
          if (branchSelect.value === 'retry') {
            fetchBranches()
          }
        })
      }
    }

    // 清除日志
    clearLogBtn.addEventListener('click', () => {
      logDiv.innerHTML = ''
      updateStatus('ready', '就绪')
      addLog('[系统] 日志已清除', 'info')
    })

    // 复制日志
    copyLogBtn.addEventListener('click', () => {
      const logs = logDiv.textContent
      if (!logs.trim()) return

      const textArea = document.createElement('textarea')
      textArea.value = logs
      document.body.appendChild(textArea)
      textArea.select()
      document.execCommand('copy')
      document.body.removeChild(textArea)

      addLog('[系统] 日志已复制到剪贴板', 'info')
    })

    // 部署按钮功能
    deployBtn.addEventListener('click', async () => {
      const branch = branchSelect.value
      const env = envSelect.value

      // 验证输入
      if (!branch || branch === 'retry') {
        branchSelect.style.borderColor = '#f85149'
        setTimeout(() => {
          branchSelect.style.borderColor = ''
        }, 2000)
        addLog('[错误] 请选择有效的分支', 'error')
        return
      }

      if (!env) {
        envSelect.style.borderColor = '#f85149'
        setTimeout(() => {
          envSelect.style.borderColor = ''
        }, 2000)
        addLog('[错误] 请选择部署环境', 'error')
        return
      }

      // 准备部署
      updateStatus('progress', '部署中...')
      deployBtn.disabled = true

      // 显示部署信息
      const envName = env === 'test' ? '测试环境' : '生产环境'
      addLog(`[系统] 开始部署分支: ${branch} 到 ${envName}`, 'info')

      try {
        // 调用部署API
        const response = await fetch('http://localhost:3333/deploy', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            branch: branch,
            env: env
          })
        })

        // 检查响应状态
        if (!response.ok) {
          throw new Error(`部署失败: ${response.status}`)
        }

        // 处理流式响应
        const reader = response.body.getReader()
        const decoder = new TextDecoder('utf-8')
        let logData = ''

        while (true) {
          const { value, done } = await reader.read()
          if (done) break

          const text = decoder.decode(value, { stream: true })
          logData += text

          // 处理完整行
          const lines = logData.split('\n')
          logData = lines.pop() || ''

          for (const line of lines) {
            if (line.trim() !== '') {
              addLog(`[部署] ${line}`, 'info')
            }
          }
        }

        // 处理剩余数据
        if (logData.trim() !== '') {
          addLog(`[部署] ${logData}`, 'info')
        }

        // 部署成功
        addLog('[系统] ✅ 部署成功完成', 'info')
        updateStatus('success', '部署完成')
      } catch (error) {
        console.error('部署失败:', error)
        addLog(`[错误] 部署失败: ${error.message}`, 'error')
        updateStatus('error', '部署失败')
      } finally {
        deployBtn.disabled = false
      }
    });
  </script>
</body>

</html>